/*
 * Copyright (c) Huawei Device Co., Ltd. 2024. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ef_ac_rules.h"

#include "common_utils.h"
#include "der_parser.h"
#include "ef_ac_conditions.h"
#include "loghelper.h"

namespace OHOS {
namespace SE {
EfAcRules::EfAcRules() : EfParser()
{
}

EfAcRules::~EfAcRules()
{
}

bool EfAcRules::ParseAcRuleFileData(const std::vector<uint8_t> &fileData)
{
    std::vector<uint8_t> aid;
    std::shared_ptr<DerParser> der = std::make_shared<DerParser>(fileData);
    uint32_t tag = 0;
    while (!der->IsParsingEnd()) {
        der->GetTlvDataLength(ASN1_SEQUENCE);
        switch (der->GetTlvType()) {
            case TAG_RESTRICT_AID:
                der->GetTlvDataLength(ASN1_OCTET_STRING);
                aid = der->GetTlvData();
                tag = AID_REF_DO_TAG;
                break;
            case TAG_EMPTY_AID:
                aid.clear();
                tag = AID_REF_DO_EMPTY_TAG;
                break;
            case TAG_DEFAULT_APP:
                aid = DEFAULT_APP;
                tag = AID_REF_DO_TAG;
                break;
            default:
                ErrorLog("invalid tag.");
                return false;
        }
        std::vector<uint8_t> acConditionPath = der->ParseEfPath();
        if (acConditionPath.size() == 0) {
            continue;
        }
        std::string pathString = CommonUtils::BytesArrayToHexString(&acConditionPath[0], acConditionPath.size());
        std::shared_ptr<AidRefDo> tempAidRefDo = std::make_shared<AidRefDo>(aid, true, tag);
        std::shared_ptr<EfAcConditions> tempAcCondition = std::make_shared<EfAcConditions>(tempAidRefDo);
        if (acConditionDataCache_.count(pathString) > 0) {
            tempAcCondition->ParseAcConditionFileData(acConditionDataCache_[pathString]);
        } else {
            tempAcCondition->ParseAcConditionFileDataByPath(acConditionPath);
            if (tempAcCondition->GetData().size() != 0) {
                acConditionDataCache_.insert(pair<std::string, std::vector<uint8_t>>(
                    pathString, tempAcCondition->GetData()));
            }
        }
    }
    return true;
}

bool EfAcRules::ParseAcRulesFileByPath(const std::vector<uint8_t> &acRulePath)
{
    InfoLog("Parsing AC RULES file by path");
    acConditionDataCache_.clear();
    uint16_t rspApdu = 0;
    if (!ReadFileByPath(acRulePath, rspApdu)) {
        ErrorLog("fail to read ac rules file, rspApdu[%{public}x]", rspApdu);
        return false;
    }

    std::vector<uint8_t> acRuleFileData = ReadFileByDataSize(0, -1);
    return ParseAcRuleFileData(acRuleFileData);
}
}  // namespace SE
}  // namespace OHOS
